package com.bw.lib_http

import android.annotation.SuppressLint
import com.alibaba.android.arouter.launcher.ARouter
import com.bw.lib_base.constants.BaseConst
import com.bw.lib_base.path.RouterPath
import com.tencent.mmkv.MMKV
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONObject
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.net.Proxy
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager

/**
 * 网络封装
 *
 * OkHttp的基本原理
 * 1.底层基于HttpURLConnection实现
 * 2.使用线程池管理所有请求连接（连接池），默认最大可以开启64个连接
 * 3.请求和返回处理时采用责任链的设计模式（拦截器）
 * 4.采用调度器管理请求
 *
 * 以下过装存在的问题：
 * 1.OKHttpClient和Retrofit存在多份实例
 * 2.会开启多个线程池，导致内存浪费
 * 3.连接清求没有复用，导致线程浪费
 * 4.存在单个连接时间过长
 * 5.没有对请求进行统一处理，如关闭请求
 */
object HttpManager {

    /**
     * 获取OkHttpClient
     */
    @SuppressLint("SuspiciousIndentation")
    private fun getOkHttpClient():OkHttpClient{
        var okBuilder= OkHttpClient.Builder()
             okBuilder.apply {
                 connectTimeout(BaseConst.CONNECT_TIME_OUT, TimeUnit.SECONDS)//连接超时
                 writeTimeout(BaseConst.WRITE_TIME_OUT, TimeUnit.SECONDS)//写超时
                 readTimeout(BaseConst.READ_TIME_OUT, TimeUnit.SECONDS)//读超时
                 //设置接口请求拦截日志
                 if (BuildConfig.isOpenLog){
                     addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))//日志拦截器
                 }

                 //Header参数拦截器
                 addInterceptor(getHeaderInterceptor())

                 //服务器异常拦截器
                 addInterceptor(getServiceExceptionInterceptor())

                 //添加Https的支持
                 sslSocketFactory(sslSocketFactory,trustManager)

                 //防止抓包软件获取接口数据
                 proxy(Proxy.NO_PROXY)
             }

        return okBuilder.build()
    }

    private val sslSocketFactory:SSLSocketFactory
        get() = try {
            val sslContext=SSLContext.getInstance("SSL")
            sslContext.init(null, arrayOf(trustManager),SecureRandom())
            sslContext.socketFactory
        }catch (e:Exception){
            throw RuntimeException(e)
        }

    private val trustManager:X509TrustManager
        get()=object :X509TrustManager{
            override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
            }

            override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {

            }

            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }
        }


    /**
     * 获取Retrofit
     */
    fun getRetrofit(): Retrofit {
        var retrofitBuilder= Retrofit.Builder()
        //apply扩展函数用于对象赋值
        retrofitBuilder.apply {
            baseUrl(BuildConfig.Base_URL)
            client(getOkHttpClient())
            addConverterFactory(GsonConverterFactory.create())
        }
        return retrofitBuilder.build()
    }

    /**
     * 请求头拦截器
     */

    private fun getHeaderInterceptor():Interceptor{
        return object : Interceptor{
            override fun intercept(chain: Interceptor.Chain): Response {
                //获取Token
                var token = MMKV.defaultMMKV().decodeString("token","a2208_park")
                val newBuilder = chain.request().newBuilder()
                if (token != null) {
                    newBuilder.header("token",token).build()
                }

                //获取AccessId
                var accessId=MMKV.defaultMMKV().decodeString("accessId","")
                if (accessId!=null){
                    newBuilder.header("accessId",accessId).build()
                }

                //执行请求
                val newRequest = newBuilder.build()
                val response = chain.proceed(newRequest)

                //验证Token是否过期
                if (response.code==403||response.code==401){
                    ARouter.getInstance().build(RouterPath.PATH_LOGIN_PAGE).navigation()
                }

                return response
            }

        }
    }

    /**
     * 服务器异常拦截器
     * 责任链模式
     */
    private fun getServiceExceptionInterceptor():Interceptor{
        return object:Interceptor{
            override fun intercept(chain: Interceptor.Chain): Response {
                var errorResponse = chain.proceed(chain.request())
                var responseBuilder = errorResponse.newBuilder()
                if (errorResponse.code==500){
                    var newJson=JSONObject()
                    newJson.put("code",500)
                    newJson.put("message","服务器异常，请联系客服！")
                    responseBuilder.body(newJson.toString().toResponseBody("application/json=UTF-8".toMediaTypeOrNull()))
                }

                return responseBuilder.build()
            }

        }
    }

    /**
     * 对外获取ApiService实例对象
     */

    fun <T> getApiServer(clazz: Class<*>):T{
        return getRetrofit().create(clazz) as T
    }

}